package com.bb.flow.parser.impl.parsejson;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.bb.flow.api.exception.ParseException;
import com.bb.flow.config.AbstractConfigNode;
import com.bb.flow.config.ConditionInfo;
import com.bb.flow.config.FlowInfo;
import com.bb.flow.parser.NodeParser;
import com.bb.flow.parser.ObjectCreator;
import com.bb.flow.parser.PropertyAssignment;
import com.bb.flow.parser.impl.FlowInit;
import com.bb.flow.parser.impl.parsejson.parsenode.ParseClassInfo;
import com.bb.flow.parser.impl.parsejson.parsenode.ParseCondition;
import com.bb.flow.parser.impl.parsejson.parsenode.ParseNodeBaseInfo;
import com.bb.flow.parser.impl.parsejson.parsenode.ParseNodeDispatcher;
import com.bb.flow.service.exception.FlowTemplateNameNullException;
import com.bb.flow.util.Tools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author bigbeard
 * JSON内容解析器
 */
public class JsonParser implements NodeParser {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    private ParseCondition parseCondition;
    private ParseNodeDispatcher parseNodeDispatcher;
    private ObjectCreator objectCreator;
    private PropertyAssignment propertyAssignment;
    private boolean createInstance = true;

    /**
     * 构造函数,初始化
     */
    public JsonParser() {
        init();
        parseNodeDispatcher.init();
    }

    /**
     * 设置条件解析类
     *
     * @param parseCondition 解析类
     */
    private void setParseCondition(ParseCondition parseCondition) {
        this.parseCondition = parseCondition;
    }

    /**
     * 设置节点解析类
     *
     * @param parseNode 解析类
     */
    private void setParseNodeDispatcher(ParseNodeDispatcher parseNode) {
        this.parseNodeDispatcher = parseNode;
    }


    @Override
    public FlowInfo parse(String context) throws FlowTemplateNameNullException, ParseException {
        if (null == parseNodeDispatcher || null == parseCondition) {
            logger.error("请在调用解析方法之前设置,条件解析类,解析节点类和解析变量类");
            return null;
        } else {
            FlowInit objectInit = new FlowInit();
            objectInit.setCreateObject(this.createInstance);
            objectInit.setObjectCreator(this.objectCreator);
            objectInit.setPropertyAssignment(this.propertyAssignment);
            FlowInfo flowInfo = parseFlow(context);
            if (null == flowInfo) {
                return null;
            }
            objectInit.initFlow(flowInfo);
            return flowInfo;
        }
    }

    /**
     * 注入对象创建器
     *
     * @param objectCreator 创建器
     */
    @Override
    public void setObjectCreator(ObjectCreator objectCreator) {
        this.objectCreator = objectCreator;
    }

    @Override
    public void setPropertyAssignment(PropertyAssignment propertyAssignment) {
        this.propertyAssignment = propertyAssignment;
    }

    /**
     * 将对象转成字符串
     *
     * @param flowInfo 流程
     * @return 字符串的流程
     */
    @Override
    public String unParse(FlowInfo flowInfo) {
        return JSONObject.toJSONString(flowInfo);
    }

    @Override
    public void setCreateNodeInstance(boolean isCreate) {
        this.createInstance = isCreate;
    }

    private void init() {
        //todo 可以采用注入的方式来解除直接耦合
        ParseClassInfo parseClassInfo = new ParseClassInfo();
        ParseNodeBaseInfo parseNodeBaseInfo = new ParseNodeBaseInfo();

        ParseCondition parseCondition = new ParseCondition();
        parseCondition.setParseClassInfo(parseClassInfo);
        this.setParseCondition(parseCondition);

        ParseNodeDispatcher parseNodeDispatcher = new ParseNodeDispatcher();
        parseNodeDispatcher.setParseClassInfo(parseClassInfo);
        parseNodeDispatcher.setParseNodeBaseInfo(parseNodeBaseInfo);
        parseNodeDispatcher.setParseCondition(parseCondition);

        this.setParseNodeDispatcher(parseNodeDispatcher);

    }


    private FlowInfo parseFlow(String jsonContext) throws FlowTemplateNameNullException, ParseException {

        FlowInfo flowInfo = new FlowInfo();

        JSONObject parse = JSONObject.parseObject(jsonContext);

        String flowTemplateName = parse.getString("FlowTemplateName");
        if (Tools.isEmptyOrNull(flowTemplateName)) {
            throw new FlowTemplateNameNullException("流程模版名称为null,系统无法解析");
        }
        String otherInfo = parse.getString("OtherInfo");
        if (!Tools.isEmptyOrNull(otherInfo)) {
            flowInfo.setOtherInfo(otherInfo);
        }
        flowInfo.setFlowTemplateName(flowTemplateName);
        JSONObject condition = parse.getJSONObject("Condition");
        if (null != condition) {
            ConditionInfo conditionInfo = parseCondition.parseCondition(condition, "流程模版启动条件", flowTemplateName);
            flowInfo.setCondition(conditionInfo);
        }

        JSONArray flowNodeJson = parse.getJSONArray("FlowNode");
        if (null == flowNodeJson || flowNodeJson.size() <= 0) {
            logger.error("流程模版[{}]中未配置节点信息,流程无效", flowTemplateName);
            return null;
        }
        for (int i = 0; i < flowNodeJson.size(); i++) {
            JSONObject jsonObject = flowNodeJson.getJSONObject(i);
            AbstractConfigNode abstractConfigNode = parseNodeDispatcher.dispatcherParseNode(jsonObject, flowTemplateName);
            if (abstractConfigNode != null) {
                flowInfo.addFlowNode(abstractConfigNode);
            }
        }
        return flowInfo;
    }
}
